package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.QuestionApi;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.*;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.User;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendQueryDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class TanhuaService {
    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserApi userApi;

    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;

    @DubboReference
    private UserLikeApi userLikeApi;

    @DubboReference
    private FriendApi friendApi;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;
    @Autowired
    private RedisTemplate<String ,String > redisTemplate;

    public TodayBest todayBest() {
        Long id = UserHolder.getId();
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(id);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(3l);
            recommendUser.setScore(80d);
        }
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
        return todayBest;
    }

    public PageResult recommendList(RecommendQueryDto recommendQueryDto) {
        Long toUserId = UserHolder.getId();
        Integer page = recommendQueryDto.getPage();
        Integer pagesize = recommendQueryDto.getPagesize();
        PageResult pageResult = recommendUserApi.queryRecommendUsers(toUserId, page, pagesize);
        List<RecommendUser> recommendUserList = (List<RecommendUser>) pageResult.getItems();
        List<TodayBest> todayBestList = new ArrayList<>();
        List<Long> userIds = CollUtil.getFieldValues(recommendUserList, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds);

        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
            todayBestList.add(todayBest);
        }
        pageResult.setItems(todayBestList);
        return pageResult;
    }

    public TodayBest personalInfo(Long recommendUserId) {
        UserInfo userInfo = userInfoApi.findById(recommendUserId);
        RecommendUser recommendUser = recommendUserApi.findById(recommendUserId, UserHolder.getId());
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);

        //保存访客信息
        Visitors visitors = new Visitors();
        visitors.setUserId(recommendUserId);
        visitors.setVisitorUserId(UserHolder.getId());
        visitors.setScore(recommendUser.getScore());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitorsApi.saveOrUpdate(visitors);

        return todayBest;
    }

    public String question(Long userId) {
        Question question = questionApi.findByUserId(userId);
        return question == null ? "你喜欢大海吗？" : question.getTxt();
    }

    public void replyQuestion(Long targetUserId, String reply) throws JsonProcessingException {
        //检测是否冻结
        String reason = redisTemplate.opsForValue().get(Constants.FreezeComment_KEY + UserHolder.getId());
        Long restTime = redisTemplate.opsForValue().getOperations().getExpire(Constants.FreezeComment_KEY + UserHolder.getId(), TimeUnit.HOURS);
        if (reason != null) {
            throw new BusinessException("该用户处于冻结发言状态, 请联系客服处理", ErrorResult.freezeCommentError("\n 解除冻结剩余时间"+restTime+"小时"+"\n 冻结原因"+reason));
        }

        Long userId = UserHolder.getId();
        User user = userApi.findById(userId);
        UserInfo userInfo = userInfoApi.findById(userId);
        Question question = questionApi.findByUserId(targetUserId);
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("userId", userId);
        jsonMap.put("huanXinId", user.getHxUser());
        jsonMap.put("nickname", userInfo.getNickname());
        jsonMap.put("strangerQuestion", question == null ? "你喜欢大海吗？" : question.getTxt());
        jsonMap.put("reply", reply);
        String json = new ObjectMapper().writeValueAsString(jsonMap);
        huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + targetUserId, json);
    }

    public List<TodayBest> queryCardsList() {
        //1.查询mongodb得到推荐好友
        Long userId = UserHolder.getId();
        List<RecommendUser> recommendUserList = recommendUserApi.queryCardsList(userId);

        //2.如果推荐好友为空，则使用默认推荐
        if (CollUtil.isEmpty(recommendUserList)) {
            String[] recommendUserArray = recommendUser.split(",");
            recommendUserList = new ArrayList<>();
            for (String recommendUserId : recommendUserArray) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(recommendUserId));
                recommendUser.setToUserId(userId);
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUserList.add(recommendUser);
            }
        }

        //3.提取推荐列表的推荐人id集合
        List<Long> recommendUserIds = CollUtil.getFieldValues(recommendUserList, "userId", Long.class);

        //4.根据推荐人id集合批量查询出userinfo
        Map<Long, UserInfo> recommendUserInfos = userInfoApi.findByIds(recommendUserIds);

        //5.将userinfo和recommend组装成TodayBest列表返回
        List<TodayBest> todayBestList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = recommendUserInfos.get(recommendUser.getUserId());
            TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
            todayBestList.add(todayBest);
        }

        return todayBestList;
    }

    public void likeUser(Long likeUserId) {
        //1.往userlike中插入一条记录
        Long userId = UserHolder.getId();
        UserLike userLike = new UserLike();
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setIsLike(true);
        userLikeApi.save(userLike);

        //2.判断两个用户是否相互喜欢
        boolean isEachLike = userLikeApi.isEachLike(userId, likeUserId);

        //3.如果相互喜欢，需要删除userlike中的两条记录，然后成为好友，环信上也添加好友
        if (isEachLike) {
            userLikeApi.deleteEachLike(userId, likeUserId);
            friendApi.save(userId, likeUserId);
            huanXinTemplate.contactUsers(Constants.HX_USER_PREFIX + userId, Constants.HX_USER_PREFIX + likeUserId);
        }
    }

    public void notLikeUser(Long likeUserId) {
        Long userId = UserHolder.getId();
        UserLike userLike = new UserLike();
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setIsLike(false);
        userLikeApi.save(userLike);
    }

    public List<NearUserVo> searchNearUser(String gender, Integer distance) {
        Long userId = UserHolder.getId();
        List<Long> nearUserIds = userLocationApi.searchNearUser(userId, distance);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(nearUserIds);
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        for (UserInfo userInfo : userInfoMap.values()) {
            if (userInfo.getGender().equalsIgnoreCase(gender) && userInfo.getId() != userId) {
                NearUserVo vo = NearUserVo.init(userInfo);
                nearUserVoList.add(vo);
            }
        }
        return nearUserVoList;
    }
}


